unit URender;

interface

uses Classes, Windows, ExtCtrls, SysUtils, Math, Graphics, Forms, Dialogs,
  GraphUtil, UPictureList, UMap, UPictureName, UPlayer;

type

  TRenderThread = class(TThread)
  private
    Game: TObject;
    GameImage: TBitmap;
    Height: integer;
    ThreadEnde: boolean;
    Width: integer;
    FRunning: boolean;
    procedure SetRunning(const Value: boolean);

  protected
    procedure Execute; override;
    procedure DrawLeben(Count: integer; TexturePack: TPictureList);

  public
    procedure UpdateImage;
    procedure GetScreenImage;
    procedure clearBackground();
    procedure DrawObjects();

    constructor create(Game: TObject);
    destructor Free();

    property Running: boolean read FRunning write SetRunning;

  end;

implementation

uses UScreen, UGame;

{ TRender }

constructor TRenderThread.create(Game: TObject);
begin
  Self.Game := Game;
  Self.Running := False;
  inherited create(False);
end;

procedure TRenderThread.DrawLeben(Count: integer; TexturePack: TPictureList);
var
  i: integer;
begin
  for i := 1 to Count do
    Self.GameImage.Canvas.Draw(i * 30, 10, TexturePack.GetNamedPicture(i_Herz)
        .Graphic);
end;

procedure TRenderThread.DrawObjects;
var
  Game: TGame;
  OffsetX: integer;
  OffsetY: integer;
  SWidth: integer;
  SHeight: integer;
  Picture: TPicture;
  Objekte: TMapObjekts;
  TexturePack: TPictureList;
  i: integer;
begin
  Game := TGame(Self.Game);
  OffsetX := Game.getOffsetX;
  OffsetY := Game.getOffsetY;

  SWidth := Game.getScreen.Width;
  SHeight := Game.getScreen.Height;

  TexturePack := Game.getTexturePack;

  // Erst die Objekte zeichnen
  Objekte := Game.getMap.GetMapObjekteByPos;

  for i := Game.getMap.GetLowestPlace(OffsetX) to Game.getMap.GetHighestPlace
    (OffsetX + SWidth) do
  begin
    if not(Objekte[i] is TPlayer) then
    begin
      Picture := TexturePack.GetNamedPicture(Objekte[i].PictureName);

      if Picture <> nil then
      begin
        if (((Objekte[i].StartX > OffsetX) and
              (Objekte[i].StartX < OffsetX + SWidth)) or
            ((Objekte[i].EndeX > OffsetX) and
              (Objekte[i].EndeX < OffsetX + SWidth))) AND
          (((Objekte[i].StartY > OffsetY) and
              (Objekte[i].StartY < OffsetY + SHeight)) or
            ((Objekte[i].Endey > OffsetY) and
              (Objekte[i].Endey < OffsetY + SHeight))) then
        begin
          GameImage.Canvas.Draw(Objekte[i].StartX - OffsetX,
            Objekte[i].StartY - OffsetY, Picture.Graphic);
        end;
      end;
    end;
  end;

  // Spieler zeichnen
  if Game.Player1 <> nil then
  begin
    Picture := TexturePack.GetNamedPicture(Game.Player1.PictureName);
    GameImage.Canvas.Draw(Game.Player1.StartX - OffsetX - 1,
      Game.Player1.StartY - OffsetY - 1, Picture.Graphic);
  end;

  if Game.Player2 <> nil then
  begin
    Picture := TexturePack.GetNamedPicture(Game.Player2.PictureName);
    GameImage.Canvas.Draw(Game.Player2.StartX - OffsetX - 1,
      Game.Player2.StartY - OffsetY - 1, Picture.Graphic);
  end;

  // Leben des Spielers zeichnen
  if Game.IsRunning then
    Self.DrawLeben(Game.ActivePlayer.Leben, TexturePack);
end;

procedure TRenderThread.clearBackground();
begin
  GameImage.Canvas.Brush.Color := RGB(250, 0, 250);
  GameImage.Canvas.Rectangle(-1, -1, (Game as TGame).getScreen.Width + 1,
    (Game as TGame).getScreen.Height + 1);
end;

procedure TRenderThread.Execute;
var
  PauseTime: integer;
begin
  PauseTime := 1000 div SCREEN_FPS;
  Self.Synchronize(GetScreenImage);
  ThreadEnde := False;
  repeat
    if Self.Running then
    begin
      // Bild berechnen
      Self.Synchronize(clearBackground);
      Self.Synchronize(DrawObjects);
      Self.Synchronize(UpdateImage);
    end;

    // Sleep berechnen
    sleep(PauseTime);
  until ThreadEnde;
  Self.Terminate;
end;

destructor TRenderThread.Free;
begin
  Self.ThreadEnde := true;
  sleep(500);
  Application.ProcessMessages;
  Self.GameImage.Free;
end;

procedure TRenderThread.GetScreenImage;
begin
  Self.GameImage := TBitmap.create;
  Self.Height := (Game as TGame).MScreen.GameImage.Height;
  Self.Width := (Game as TGame).MScreen.GameImage.Width;
  Self.GameImage.Assign((Game as TGame).MScreen.GameImage.Picture.Bitmap);
end;

procedure TRenderThread.SetRunning(const Value: boolean);
begin
  FRunning := Value;
end;

procedure TRenderThread.UpdateImage;
begin

  if (TGame(Game).MScreen.Fullscreen AND
      (TGame(Game).MScreen.ImageResizeAngle > 0)) then
  begin
    GraphUtil.ScaleImage(Self.GameImage, TGame(Game)
        .MScreen.GameImage.Picture.Bitmap, TGame(Game)
        .MScreen.ImageResizeRatio);
  end
  else
  begin
    TGame(Game).MScreen.GameImage.Picture.Bitmap.Assign(Self.GameImage);
  end;

end;

end.
